package com.laobiao.file_netty_lib.netty.client.handler;

import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.laobiao.file_netty_lib.content.LoggerUtil;
import com.laobiao.file_netty_lib.exception.FileBaseException;
import com.laobiao.file_netty_lib.netty.client.ClientBusiness;
import com.laobiao.file_netty_lib.packet.BasePacket;
import com.laobiao.file_netty_lib.packet.command.ResoultCommand;
import com.laobiao.file_netty_lib.packet.command.upload.FileUploadCommand;
import com.laobiao.file_netty_lib.packet.data.BaseDataPacket;
import com.laobiao.file_netty_lib.util.CheckCodeUtil;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;

public class ClientDataUploadBusiness extends FileUploadCommand implements ClientBusiness{
	private static final Logger logger=LoggerUtil.getLogger(ClientDataUploadBusiness.class);
	/**
	 * 通道
	 */
	private Channel channel;
	/**
	 * 发送的数据
	 */
	private byte[] sendData;
	
	/**
	 * 整个流程是否停止，异常或正常上传完成后置true
	 */
	private volatile boolean stop=false;
	
	/**
	 * 是否上传成功，流程完成且正常上传成功是置true
	 */
	private volatile boolean upload=false;
	
	/**
	 * 服务端反馈的消息
	 */
	private String msg="";
	
	/**
	 * 
	 * @param remoteFilePath 目标服务都安存储地址
	 * @param businessGroup 业务组编号
	 * @param sendData 发送的数据
	 * @param channel 通道
	 */
	public ClientDataUploadBusiness(String remoteFilePath, Integer businessGroup, byte[] sendData,Channel channel) {
		super(remoteFilePath, businessGroup, sendData.length, CheckCodeUtil.getCheckCode(sendData));
		this.channel=channel;
		this.sendData=sendData;
	}

	
	/**
	 * 写入远端错误消息
	 * @param msg
	 */
	private  void err(String msg) {
		setStatus(true,false,msg);
	}
	
	/**
	 * 执行成功
	 * @param msg
	 */
	private  void sucess(String msg) {
		setStatus(true,true,msg);
	}
	
	private  void setStatus(boolean stop,boolean upload,String msg) {
		this.stop=stop;
		this.upload=upload;
		this.msg=msg;
		if(stop) {//停止
			close();
		}
	}
	
	/**
	 * 检测是否上传成功
	 * @param timeOutSeconds 超时时间
	 * @return
	 */
	public boolean isUpload(int timeOutSeconds) {
		long defaultSleepTime=100;
		long millisecond=timeOutSeconds*1000;
		while(!stop && millisecond>0) {
			millisecond-=defaultSleepTime;
			try {
				Thread.currentThread().sleep(defaultSleepTime);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(!stop) {
			throw new FileBaseException("上传文件超时！", FileBaseException.ERR_PARAM_WRONG);
		}
		return upload;
	}
	@Override
	public void resoultPacket(BasePacket packet) {
		logger.log(Level.CONFIG,"收到服务端发来的反馈命令包！"+packet);
		/**
		 * 上传只会接收反馈命令包，其他包不管
		 */
		if (packet instanceof ResoultCommand) {
			ResoultCommand reCommand = (ResoultCommand) packet;
			if (reCommand.isStatus()) {//成功状态
				if (reCommand.getCode() == ResoultCommand.ResoultCode.Common.SERVER_RECEIVE) {// 接收过程中成功的状态信息
					
				} else if (reCommand.getCode() == ResoultCommand.ResoultCode.Common.SERVER_CHECK) {// 校验完成入库的成功信息
					logger.info("数据上传到服务器【"+getRemoteFilePath()+"】成功！");
					sucess(reCommand.getMessage());
					close();
				}
			} else {//失败状态
				logger.warning("上传失败！"+reCommand.getMessage());
				err(reCommand.getMessage());
				close();
			}
		}
	}
	
	/**
	 * 无需处理
	 */
	@Override
	public void close() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Object executStatus(int executReturnTimeOutSeconds) {
		channel.writeAndFlush(this);
		try {
			int readSize = 0;
			int from=0;
			int to=Math.min(sendData.length, 1015);
			byte[] send;
//			ByteBuf buf=Unpooled.copiedBuffer(sendData);
			long start=System.currentTimeMillis();
			while ((send=Arrays.copyOfRange(sendData, from, to)).length>0) {
				BaseDataPacket dataPacket = new BaseDataPacket(getBusinessGroup(), send);
				dataPacket.setContentSize(send.length);
				ChannelFuture fs = channel.writeAndFlush(dataPacket);
				fs.sync();
				send=null;
				if(to>=sendData.length) {
					break;
				}else {
					from=to;
					to=Math.min(to+1015,sendData.length);
				}
				
			}
			long sendTime=System.currentTimeMillis()-start;
			double sendSeconde=(sendTime)/1000.0000;
			logger.info("内容上传到远程目录【"+getRemoteFilePath()+"】完成：\n\r    用时:"+sendSeconde+"秒,速度:"+(getFileSize()/1024.000/sendSeconde)+"K/秒");
			
			// 发送上传完成命令包
			ResoultCommand reCommad = new ResoultCommand(ResoultCommand.ResoultCode.Upload.CLIENT_UPLOAD, "客户端上传完成！",
					true, getBusinessGroup());
			channel.writeAndFlush(reCommad);
			return isUpload(executReturnTimeOutSeconds);
		} catch (FileBaseException e) {
			throw e;
		}catch (Exception e) {
			ResoultCommand reCommad = new ResoultCommand(ResoultCommand.ResoultCode.Upload.CLIENT_UPLOAD,
					"客户端上传失败！" + e.getMessage(), false, getBusinessGroup());
			channel.writeAndFlush(reCommad);
			throw new FileBaseException("读取文件失败！", e, FileBaseException.ERR_PARAM_WRONG);
		} finally {
			close();
		}
		
	}

	@Override
	public Channel getChannel() {
		// TODO Auto-generated method stub
		return this.channel;
	}

}
